package com.mazaiting.instructions.base;

import com.mazaiting.rtda.MtFrame;
import com.mazaiting.rtda.MtThread;
import com.mazaiting.rtda.heap.MtClass;
import com.mazaiting.rtda.heap.MtMethod;

import java.util.Objects;

/**
 * 类初始化逻辑
 *
 * @author mazaiting
 * @since 2021/8/25
 */
public class ClassInitLogic {
    /**
     * 初始化类
     * @param thread 线程
     * @param mtClass 类实例
     */
    public static void initClass(MtThread thread, MtClass mtClass) {
        // 开始初始化
        mtClass.startInit();
        // 准备执行 <clinit> 方法
        scheduleClInit(thread, mtClass);
        // 初始化父类
        initSuperClass(thread, mtClass);
    }

    /**
     * 执行类初始化方法
     * 类初始化方法没有参数，所以不需要传递参数
     * 有可能要先执行超类的初始化方法
     * @param thread 当前线程
     * @param mtClass 当前类
     */
    private static void scheduleClInit(MtThread thread, MtClass mtClass) {
        // 获取类初始化方法
        MtMethod clInitMethod = mtClass.getClInitMethod();
        // 如果不为空, 则创建新的栈帧, 并压入线程栈
        if (Objects.nonNull(clInitMethod)) {
            MtFrame newFrame = thread.newFrame(clInitMethod);
            thread.pushFrame(newFrame);
        }
    }

    /**
     * 初始化父类
     * 如果超类的初始化还没有开始，就递归调用InitClass()函数执行超类的初始化方法，
     * 这样可以保证超类的初始化方法对应的帧在子类上面，使超类初始化方法先于子类执行
     * @param thread 当前线程
     * @param mtClass 当前类
     */
    private static void initSuperClass(MtThread thread, MtClass mtClass) {
        // 如果当前类不是接口
        if (!mtClass.isInterface()) {
            MtClass superClass = mtClass.getSuperClass();
            // 不为空并且没有初始化
            if (Objects.nonNull(superClass) && !superClass.isInitStarted()) {
                initClass(thread, superClass);
            }
        }
    }
}


















